package com.project.basis.core

import android.os.Handler
import android.os.Looper
import com.google.gson.JsonSyntaxException
import com.project.basis.entity.PaiPaiClassifyListEntity
import com.project.basis.utils.JsonUtils
import com.project.basis.utils.OnDownloadingListener
import com.project.basis.utils.SimpleCallback
import okhttp3.*
import okhttp3.MediaType.Companion.toMediaType
import okhttp3.RequestBody.Companion.toRequestBody
import java.io.File
import java.io.FileOutputStream
import java.io.IOException
import java.util.concurrent.TimeUnit

class CoreEngineKt private constructor() {

    private lateinit var okHttpClient: OkHttpClient

    private lateinit var handler: Handler

    companion object {
        val coreEngineKt: CoreEngineKt by lazy {
            CoreEngineKt()
        }
    }

    private fun getClient(): OkHttpClient {
        if (!::okHttpClient.isInitialized) {
            okHttpClient = OkHttpClient.Builder()
                .connectTimeout(10, TimeUnit.SECONDS)
                .readTimeout(20, TimeUnit.SECONDS)
                .build()
            okHttpClient.dispatcher.maxRequests = 128
            okHttpClient.dispatcher.maxRequestsPerHost = 20
        }
        if (!::handler.isInitialized) {
            handler = Handler(Looper.getMainLooper())
        }
        return okHttpClient
    }

    private fun downloadClient(
        path: String,
        request: Request,
        callback: OnDownloadingListener
    ): Call {
        val call = getClient().newCall(request)
        call.enqueue(object : Callback {
            override fun onFailure(call: Call, e: IOException) {
                if (e.message != "Canceled") {
                    handler.post { callback.onError(e) }
                }
            }

            override fun onResponse(call: Call, response: Response) {
                val inputStream = response.body!!.byteStream()
                val fileOutputStream: FileOutputStream
                try {
                    fileOutputStream = FileOutputStream(File(path))
                    val buffer = ByteArray(2048)
                    var len: Int
                    var progress = 0
                    handler.post { callback.onStart(response.body!!.contentLength()) }
                    while (inputStream.read(buffer).also { len = it } != -1) {
                        fileOutputStream.write(buffer, 0, len)
                        progress += len
                        handler.post { callback.onProgress(progress) }
                    }
                    fileOutputStream.flush()
                    handler.post { callback.onFinish(path) }
                } catch (e: IOException) {
                    e.printStackTrace()
                    handler.post { callback.onError(e) }
                }
            }
        })
        return call
    }

    private inline fun <reified T> addToClient(
        request: Request,
        callback: SimpleCallback<T>,
        boolean: Boolean = true
    ) {
        val call = getClient().newCall(request)
        call.enqueue(object : Callback {
            override fun onFailure(call: Call, e: IOException) {
                handler.post {
                    callback.onCallback(null)
                }
            }

            override fun onResponse(call: Call, response: Response) {
                handler.post {
                    try {
                        if (boolean) {
                            callback.onCallback(
                                JsonUtils.jsonToBean(
                                    response.body!!.string(),
                                    T::class.java
                                ) as T
                            )
                        } else {
                            callback.onCallback(response.body!!.string() as T)
                        }
                    } catch (e: JsonSyntaxException) {
                        callback.onCallback(null)
                    }
                }
            }
        })
    }

    fun testGetRequest(callback: SimpleCallback<String>) {
        addToClient(
            Request.Builder()
                .addHeader("accept", "application/json, text/plain, */*")
                .addHeader("accept-language", "zh-CN,zh;q=0.9")
                .addHeader(
                    "cookie",
                    "passport_csrf_token_default=200f639cd9cc6384a247827f5a6c9030; passport_csrf_token=200f639cd9cc6384a247827f5a6c9030; ttwid=1%7CtNdwlc2ZbKUQtQFPzoSVB9RhkqaIHq0yYmRAm1obAmU%7C1621230270%7C4f796a327592d708e25b3030aac2f054e05c34de480667a8b5a58064aab99f35; odin_tt=ec3bcda4e770e560879d711c7fe2d8714ac65644ac156543b6cb29557db191e6d058edb82dd29daf3d9615901d416198912cdb7c92e458ac0c115bd1c9df6728; n_mh=Y4z5_AdOOWJbJw79-zwnttTXtluIUvjmJS96Igw1DN0; sso_auth_status=3885f202626758aca3af2e93bfcf8fae; sso_auth_status_ss=3885f202626758aca3af2e93bfcf8fae; sso_uid_tt=f35fad383d6e6bed2125f7aa70d083cf; sso_uid_tt_ss=f35fad383d6e6bed2125f7aa70d083cf; toutiao_sso_user=e14df8b87beaa5bd7dcc316675c27e50; toutiao_sso_user_ss=e14df8b87beaa5bd7dcc316675c27e50; d_ticket=2f33b65b2f3e09203ed5b553ecbbd2974c74f; passport_auth_status_ss=11b035a22146804bc95073996c016796%2C3e96eae9881bfbcf99d2f3d7e8d72264; passport_auth_status=11b035a22146804bc95073996c016796%2C3e96eae9881bfbcf99d2f3d7e8d72264; ucas_sso_c0_ss=Cj8KBTEuMC4wEJ-IiZDO3IDRYBjmJiCbr7CPoY3QASiwITCIk7DM9fSbAkDwhYiFBkjwucSHBlCDvMr6uKTL0GASFCs1NrxjcwTHggjM-xM-T2cwFErU; ucas_sso_c0=Cj8KBTEuMC4wEJ-IiZDO3IDRYBjmJiCbr7CPoY3QASiwITCIk7DM9fSbAkDwhYiFBkjwucSHBlCDvMr6uKTL0GASFCs1NrxjcwTHggjM-xM-T2cwFErU; ucas_c0_ss=Cj8KBTEuMC4wEIyIh6Sq2YDRYBjmJiCbr7CPoY3QASiwITCIk7DM9fSbAkDxhYiFBkjxucSHBlCDvMr6uKTL0GASFNruy5cLzWLJYDgxwmVkMlb99vLX; sid_guard=12d81f0f39a48ad7f5bf673e33e851bb%7C1621230321%7C5184000%7CFri%2C+16-Jul-2021+05%3A45%3A21+GMT; uid_tt=dcf5f8dbd195fe3cceaaa67d00bce910; uid_tt_ss=dcf5f8dbd195fe3cceaaa67d00bce910; sid_tt=12d81f0f39a48ad7f5bf673e33e851bb; sessionid=12d81f0f39a48ad7f5bf673e33e851bb; sessionid_ss=12d81f0f39a48ad7f5bf673e33e851bb; ucas_c0=Cj8KBTEuMC4wEIyIh6Sq2YDRYBjmJiCbr7CPoY3QASiwITCIk7DM9fSbAkDxhYiFBkjxucSHBlCDvMr6uKTL0GASFNruy5cLzWLJYDgxwmVkMlb99vLX; PHPSESSID=581b1376730541ede9c7ca41318b98b3; PHPSESSID_SS=581b1376730541ede9c7ca41318b98b3; SASID=SID2_3481570283238852384; BUYIN_SASID=SID2_3481570283238852384; buyin_app_id=13; buyin_shop_type=11; gftoken=MTJkODFmMGYzOXwxNjIxMjMyNDk5Njd8fDAGBgYGBgY; MONITOR_WEB_ID=66887938-458e-47d2-8ac9-888180598304; ttcid=ec2dc1a4e818451b86c6b48c44915f3618; s_v_web_id=verify_kos81r9s_QjKok9IN_q11j_48EI_87fk_kWKnlAvr3w2y; csrf-token=MyGgLhba-y9BM5kazFHpHry-; tt_scid=2NTobkvN1VYWnc.aATb6fIfxBNJs.EiF238jCOPzEmgjsCiLz8iRJBvYq77mnOdk752f"
                )
                .addHeader(
                    "referer",
                    "https://buyin.jinritemai.com/dashboard/servicehall/daren-square"
                )
                .addHeader(
                    "sec-ch-ua",
                    "\" Not A;Brand\";v=\"99\", \"Chromium\";v=\"90\", \"Google Chrome\";v=\"90\""
                )
                .addHeader("sec-ch-ua-mobile", "?0")
                .addHeader("sec-fetch-dest", "empty")
                .addHeader("sec-fetch-mode", "cors")
                .addHeader("sec-fetch-site", "same-origin")
                .addHeader(
                    "user-agent",
                    "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36"
                )
                .url(CoreDataHandlerKt.getTikTokList())
                .get().build(), callback, false
        )
    }

    fun testJsonPostRequest(json: String, callback: SimpleCallback<PaiPaiClassifyListEntity>) {
        addToClient(
            Request.Builder().url(ServerHttpUrl.TEST_URL)
                .post(json.toRequestBody("application/json; charset=utf-8".toMediaType()))
                .build(), callback
        )
    }

    fun testPostRequest(callback: SimpleCallback<PaiPaiClassifyListEntity>) {
        addToClient(
            Request.Builder().url(ServerHttpUrl.TEST_URL)
                .post(CoreDataHandlerKt.getPostBuilder().build())
                .build(), callback
        )
    }
}